package de.thm.exa.helpers;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.Adler32;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

public class Hash
{
    public static final String PATH = "/data/ws13exa/sites/";
//	public static final String PATH = "./sites/";
	
    public static final int CRC32 = -1, ADLER32 = 0, MD5 = 1, SHA1 = 2, SHA256 = 3, HASH_CODE = 4, CHAR_HASH = 5;
    
    public static final int FUNCTION_COUNT = 7;
    
    public static long generate(int function, Object o)
    {
        function %= FUNCTION_COUNT;
        switch(function)
        {
            case 0:
                return crc32(o);
            case 1:
                return adler32(o);
            case 2:
                return md5(o);
            case 3:
                return sha1(o);
            case 4:
                return sha256(o);
            case 5:
                return hashCode(o);
            case 6:
                return charHash(o);
            default:
                // Bullshit
                return 0;
        }
    }
    
    public static long crc32(Object o)
    {
        byte[] byteArray = o.toString().getBytes();
        
        Checksum cs = new CRC32();
        cs.update( byteArray, 0, byteArray.length );
        return cs.getValue();
    }
    
    public static long adler32(Object o)
    {
        byte[] byteArray = o.toString().getBytes();
        
        Checksum cs = new Adler32();
        cs.update( byteArray, 0, byteArray.length );
        return cs.getValue();
    }
    
    public static long md5(Object o)
    {
        try
        {
            byte[] byteArray = o.toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(byteArray);
            byte[] digest = md.digest();
            
            BigInteger bigInt = new BigInteger(digest);
            return bigInt.longValue() % Integer.MAX_VALUE;
            
        } catch (NoSuchAlgorithmException ex) {
            // Bullshit
            return -1;
        }
    }
    
    public static long sha1(Object o)
    {
        try
        {
            byte[] byteArray = o.toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(byteArray);
            byte[] digest = md.digest();
            
            BigInteger bigInt = new BigInteger(digest);
            return bigInt.longValue();
            
        } catch (NoSuchAlgorithmException ex) {
            // Bullshit
            return -1;
        }
    }
    
    public static long sha256(Object o)
    {
        try
        {
            byte[] byteArray = o.toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(byteArray);
            byte[] digest = md.digest();
            
            BigInteger bigInt = new BigInteger(digest);
            return bigInt.longValue() % Integer.MAX_VALUE;
            
        } catch (NoSuchAlgorithmException ex) {
            // Bullshit
            return -1;
        }
    }
    
    public static long hashCode(Object o)
    {
        return o.hashCode() % Integer.MAX_VALUE;
    }
    
    public static long charHash(Object o)
    {
        long hash = 0;
        char[] charArray = o.toString().toCharArray();
        for(char c : charArray)
        {
            hash += c;
        }
        return hash % Integer.MAX_VALUE;
    }

    public static String toString(int function)
    {
        function %= FUNCTION_COUNT;
        switch(function)
        {
            case 0:
                return "CRC32";
            case 1:
                return "Adler32";
            case 2:
                return "MD5";
            case 3:
                return "SHA-1";
            case 4:
                return "SHA-256";
            case 5:
                return "HashCode";
            case 6:
                return "CharHash";
            default:
                // Bullshit
                return "";
        }
    }
}
